---
id: advanced-usage
title: 进阶用法
---

## 虚拟滚动

### 开关配置

数据量较大时，表格会自动开启虚拟滚动。你也可以通过表格的 `useVirtual` 属性来调整虚拟滚动功能，目前 `useVirtual` 支持以下几个值：

- `'auto'` （默认值）表示根据表格的行数或列数自动调整是否开启虚拟滚动
  - 行数量超过 100 时，自动开启纵向虚拟滚动
  - 列数量超过 100 时，自动开启横向虚拟滚动
  - 表头的横向虚拟滚动默认关闭
- `true` 开启所有虚拟滚动
- `false` 关闭所有虚拟滚动
- 传入一个对象可以分别指定 横向/纵向/表头 是否开启虚拟滚动
  - 对象的结构为 `{ horizontal?: boolean | 'auto', vertical?: boolean | 'auto', header?: boolean | 'auto' }`

此外，水平方向的虚拟滚动 要求「所有的列都有一个指定的宽度」。推荐设置 `<BaseTable defaultColumnWidth={...} />`，确保所有的列都有一个指定的宽度

### 虚拟滚动与单元格合并

在虚拟滚动开启的情况下，如果想要进行单元格合并，则要使用 `column.getSpanRect` 来进行设定：

- `column.getSpanRect` 返回一个 `SpanRect` 的对象来表示对应单元所处的合并后的位置。
- `SpanRect` 的具体类型为 `{ left: number, right: number, top: number, bottom: number }`
  - 注意其中 left/top 是 inclusive 的，right/bottom 是 exclusive 的。

不开启虚拟滚动时，单元格合并可以通过 `column.getCellProps(...)` 返回 `colSpan / rowSpan` 进行实现。

### 滚动容器(v2.4 之前)

:::note
这里描述的是 v2.4 之前版本的行为，v2.4 之后已经没有 `flowRoot` 这个属性了，滚动容器不需要再显示地进行设置。
:::

一般来说表格有如下两种滚动模式：

- 不限制表格容器的尺寸，表格随着整个页面发生滚动
  - 此时的写法： `<BaseTable ... />` （不设置 style.overflow，也不限制表格高度或宽度）
- 限制表格容器的尺寸，表格容器内发生滚动
  - 此时注意设置表格的高度或最大高度（宽度同理），并设置 `style.overflow = 'auto'`
  - 注意 height/width/maxWidth/maxHeight 是设置在表格上的，而不是设置在父节点上：
    - 正确的写法：`<BaseTable style={{ overflow: 'auto', maxHeight: 400 }} ... />`
    - **错误的写法**：~~`<div style={{ overflow: 'auto', maxHeight: 400 }}> <BaseTable ... /> </div>`~~
  - 从另一个角度讲，如果为表格设置了 `style.overflow = 'auto'`，则必须为表格设置高度或最大高度

除了以上两种滚动模式之外，如果你想让表格在指定的容器内进行滚动，可以配置 `props.flowRoot`，该 prop 可指定表格发生滚动的 [BFC](https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context)。

表格的上层元素**不能**设置 `style.transform`。上层元素中出现缩放或平移时，表格内部可能无法获取正确的 DOM 尺寸。

### 滚动容器(v2.4+)

表格组件会自动向上寻找第一个滚动容器，并在该容器内发生虚拟滚动。

你可以为表格设置 `styles.overflow=auto` 和 `styles.height = 300px`（也可以设置 width、maxWidth 或 maxHeight），也可以在表格的上层某个元素上设置这些样式。如果没有设置这样样式，表格将在 window 上发生虚拟滚动。

```jsx
// 滚动发生在表格内部
<BaseTable style={{ overflow: 'auto', maxHeight: 400 }} />

// 滚动发生在指定的 div.scroll-container
<div style={{ transform: 'scale(0.8)' }}>
  <div className="scroll-container" style={{ overflow: 'auto', width: 500, height: 300 }}>
    <BaseTable />
  </div>
</div>

// 滚动发生在 window 上
<html>
  <body>
    <h1 />
    <p />
    <p />
    <BaseTable />
    <footer />
  </body>
</html>
```

表格的上层元素**支持**设置 `style.transform`，可以出现简单的缩放、平移和旋转。

### 预估行高

在元素被渲染在页面之前，组件是无法获取该元素的尺寸的。为了展示尽量真实的滚动条，表格组件内部需要算出所有行的高度之和。在一行没有被渲染之前，表格内部会使用 `props.estimatedRowHeight` (默认值为 48）来作为该行的高度，从而计算所有行的高度和。

在实际使用时，实际行高可能与预估行高有较大出入，此时可以设置 `estimatedRowHeight` 来提升预估高度的准确性。

## 锁列

### 锁列的传递性

在有列嵌套的情况下（通过 `column.children` 设置列的子节点，形成列的嵌套结构），锁列具有传递性：

- 如果一个父节点设置了锁列 `lock=true`，则其所有子节点将自动被设置为 `lock=true`
- 如果一个节点设置了锁列 `lock=true`，则其父节点和所有祖先节点将被设置为 `lock=true`

此外，如果所有的列都设置了 `lock=true`，则整个表格的锁列将不生效。

### 左侧锁列 or 右侧锁列

锁定方向 取决于该列在 columns 中的下标：

- 下标为 0, 1, 2, ... 左侧锁定
- 下标为 n-1, n-2, n-3, ... 右侧锁定

## getValue 与 render

`column.getValue` 与 `column.render` 都会影响到单元格的渲染内容，但两者有「语义」上的区别：

- `column.getValue` 用于自定义取数方法
  - 默认的取数方法为 `row => row[column.code]`
  - getValue 的返回值应当是一个可被序列化的值，该返回值将作为「单元格的值」
- `column.render` 用于自定义单元格的渲染方法
  - render 可以返回 ReactNode 以在页面上渲染更加丰富的元素

导出表格数据时，「单元格的值」将会导出至 excel 或 json 文件。

## components 替换

表格内部用到一些子组件来实现加载动画、空表格展现效果等，上层可以通过 `props.components` 覆盖内部的默认子组件，实现一些自定义的效果。

目标表格支持的自定义子组件较少，列表如下：

- `LoadingIcon` 自定义加载图标
- `EmptyContent` 数据为空时表格的展示内容
- `LoadingContentWrapper` 自定义表格内容的 wrapper div，可用于实现自定义的加载效果
